package cool.webstudy.admin.utils.aspect.request;

import cool.webstudy.admin.constant.enums.rescode.CommonResCodeEnum;
import cool.webstudy.admin.exception.BusinessException;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 莫振双
 * @date 2024/8/2 14:41
 * @description: 请求参数检查
 */
@Aspect
@Component
@Slf4j
public class RequestParameterCheckAspect {
    /**
     * 以方法或类上自定义的注解@RequestParameterCheck为切入点
     * 其中@annotation匹配方法上的注解；@within匹配类上的注解
     */
    @Pointcut("@annotation(RequestParameterCheck) || @within(RequestParameterCheck)")
    public void controllerMethods() {
    }

    @Before("controllerMethods()")
    public void checkParameters(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Parameter[] parameters = method.getParameters();

        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            Annotation[] annotations = parameter.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().equals(RequestBody.class) || annotation.annotationType().equals(RequestParam.class)) {
                    Object arg = parameter;
                    checkFields(arg);
                }
            }
        }
    }

    private void checkFields(Object arg) {

        List<String> emptyFields = new ArrayList<>();

        Field[] fields = arg.getClass().getDeclaredFields();
        //检查 NotNull注解
        validFieldNotNull(arg, fields, emptyFields);
        // 判断是否有属性为空的字段
        if (!emptyFields.isEmpty()) {
            // 处理属性为空的逻辑，例如返回错误信息或抛出异常
            throw new BusinessException(CommonResCodeEnum.RC_PARAM_NOTNULL, emptyFields);
        }
    }

    private void validFieldNotNull(Object arg, Field[] fields, List<String> emptyFields) {
        for (Field field : fields) {
            // 判断字段是否加了NotNull注解
            if (field.isAnnotationPresent(Schema.class)) {
                // 设置字段可访问，否则会抛出IllegalAccessException异常
                field.setAccessible(true);
                try {
                    Schema schema = field.getAnnotation(Schema.class);
                    // 判断字段值是否为空
                    if (schema.required() && (field.get(arg) == null || field.get(arg) == "")) {
                        emptyFields.add(field.getName());
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}
